<template>
  <div class="personal-message-setting">
    <div class="personal-message personal-message-box">
      <h2 class="message-title">个人信息</h2>
      <div class="inner-personal-message">
        <div class="info-item">
          <label class="info-label">用户头像：</label>
          <div class="info-content">
            <div class="img-box" @click="showAvatarDialog = true">
              <div class="avatar-mask">
                <p>点击修改头像</p>
              </div>
              <div class="no-avatar" v-if="!userInfo.avatar">
                <p>{{ userInfo.name[0] }}</p>
              </div>
              <div v-else class="has-avatar">
                <img :src="libPath + userInfo.avatar" alt="" />
              </div>
            </div>
          </div>
        </div>
        <div class="info-item">
          <label class="info-label">姓名：</label>
          <div class="info-content">
            <p>{{ userInfo.name }}</p>
          </div>
        </div>
        <div class="info-item">
          <label class="info-label">所属角色：</label>
          <div class="info-content">
            <el-tag v-for="(item, index) in userInfo.roleNames" :key="index" style="margin-right: 4px;">{{ item }}</el-tag>
          </div>
        </div>
      </div>
    </div>
    <div class="edit-password personal-message-box">
      <h2 class="message-title">
        登录设置
        <span class="tips">账号在一个月内只能修改五次密码，请妥善保管好您的密码。</span>
      </h2>
      <div class="inner-personal-message">
        <div class="info-item">
          <label class="info-label">用户账号：</label>
          <div class="info-content">
            <p style="display: flex">
              <span style="line-height: 32px">{{ userInfo.account }}</span>
              <el-button type="primary" text style="margin-left: 10px" @click="handleEditAccount">修改</el-button>
            </p>
          </div>
        </div>
        <div class="info-item">
          <label class="info-label">用户密码：</label>
          <div class="info-content">
            <p>
              <span style="line-height: 32px">您已设置密码</span>
              <el-button type="primary" text style="margin-left: 10px" @click="handleEditPass">修改密码</el-button>
            </p>
          </div>
        </div>
      </div>
    </div>
    <el-dialog v-model="showAvatarDialog" title="头像选择">
      <div class="avatar-list">
        <div class="online-upload-item" :class="{ 'is-choose': chooseAvatar === item }" v-for="item in avatarList" :key="item" @click="handleChooseAvatar(item)">
          <img :src="libPath + item" alt="" />
          <div class="upload-item-checkbox">
            <el-icon><Check /></el-icon>
          </div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="submitAvatar" :loading="submitLoading">确认</el-button>
          <el-button @click="showAvatarDialog = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
    <el-dialog v-model="showAccountEditDialog" title="账号修改" width="400px">
      <div>
        <el-form ref="accountFormRef" :model="accountForm" :rules="accountRule" label-width="80px">
          <el-form-item prop="account" label="新账号">
            <el-input v-model="accountForm.account"></el-input>
          </el-form-item>
          <el-form-item prop="code" label="验证码">
            <div style="display: flex; gap: 10px;">
              <el-input v-model="accountForm.code"></el-input>
              <el-button 
                :disabled="isSending" 
                @click="sendVerifyCode"
              >
                {{ isSending ? `${countdown}s后重试` : '发送验证码' }}
              </el-button>
            </div>
          </el-form-item>
        </el-form>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showAccountEditDialog = false">取消</el-button>
          <el-button type="primary" @click="submitAccount(accountFormRef)" :loading="submitLoading">确认</el-button>
        </span>
      </template>
    </el-dialog>
    <el-dialog v-model="showPasswordEditDialog" title="修改密码" width="500px">
      <div>
        <el-form ref="passwordFormRef" :model="passwordForm" :rules="passwordRules" label-width="70px">
          <el-form-item prop="account" label="账号">
            <el-input v-model="passwordForm.account" disabled></el-input>
          </el-form-item>
          <el-form-item prop="oldPassword" label="原密码">
            <el-input v-model="passwordForm.oldPassword" type="password" show-password disabled></el-input>
          </el-form-item>
          <el-form-item prop="newPassword" label="新密码">
            <el-input v-model="passwordForm.newPassword" type="password" show-password></el-input>
          </el-form-item>
          <el-form-item prop="confirmNewPassword" label="确认密码">
            <el-input v-model="passwordForm.confirmNewPassword" type="password" show-password></el-input>
          </el-form-item>
        </el-form>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showPasswordEditDialog = false">取消</el-button>
          <el-button type="primary" @click="submitPassword(passwordFormRef)" :loading="submitLoading">确认</el-button>
        </span>
      </template>
    </el-dialog>
    <el-dialog v-model="verifyPasswordDialog" title="密码验证" width="400px">
      <div>
        <el-form ref="verifyPasswordFormRef" :model="verifyPasswordForm" :rules="verifyPasswordRules" label-width="70px">
          <el-form-item prop="password" label="当前密码">
            <el-input v-model="verifyPasswordForm.password" type="password" show-password></el-input>
          </el-form-item>
        </el-form>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="verifyPasswordDialog = false">取消</el-button>
          <el-button type="primary" @click="verifyPassword(verifyPasswordFormRef)" :loading="submitLoading">确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { Check } from '@element-plus/icons-vue'
import { getUserInfo, editAvatar, editAccount, resetPassword, validPassword, getPhoneVarCode } from '@/api/user'
import { getFileList } from '@/api/setting'
import { reactive, ref, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'

const router = useRouter()
const store = useStore()
const isPasswordVerified = ref(false)
const libPath = computed(() => {
  if (!store.state.base.groupSetting.commonResources) return ''
  const env = 'libPath_' + process.env.NODE_ENV
  const url = store.state.base.groupSetting.commonResources[env]
  return url
})
const defaultUserInfo = {
  id: 0,
  role: '',
  introduction: '',
  account: '',
  avatar: '',
  name: '',
  recent_login_time: '',
  recent_login_ip: '',
  strategy: []
}
const userInfo = reactive(Object.assign({}, defaultUserInfo))

const avatarList = ref([])
const getAvatarList = async () => {
  const res = await getFileList({
    bucketName: 'lib',
    prefix: 'images/avatar/'
  })
  if (res.code === 20000) {
    avatarList.value = res.data
  }
}
getAvatarList()
const chooseAvatar = ref(userInfo.avatar)
const showAvatarDialog = ref(false)
const submitLoading = ref(false)
const handleChooseAvatar = avatar => {
  if (avatar === chooseAvatar.value) chooseAvatar.value = ''
  else chooseAvatar.value = avatar
}

const submitAvatar = () => {
  submitLoading.value = true
  editAvatar({ avatar: chooseAvatar.value }).then(res => {
    if (res.code === 20000) {
      userInfo.avatar = chooseAvatar.value
      store.commit('base/SET_USER_AVATAR', userInfo.avatar)
      submitLoading.value = false
      showAvatarDialog.value = false
    }
  })
}

const accountFormRef = ref()
const showAccountEditDialog = ref(false)
const accountForm = reactive({
  account: '',
  code: ''
})
const validateAccount = (rule, value, callback) => {
  const phoneReg = /^1[3-9]\d{9}$/
  if (value === '') {
    callback(new Error('账号不能为空'))
  } else if (!phoneReg.test(value)) {
    callback(new Error('请输入正确的手机号'))
  } else if (value === userInfo.account) {
    callback(new Error('新账号不能与当前账号相同'))
  } else {
    callback()
  }
}
const accountRule = reactive({
  account: [{ validator: validateAccount, trigger: 'blur' }],
  code: [
    { required: true, message: '请输入验证码', trigger: 'blur' }
  ]
})
const submitAccount = async formEl => {
  if (!formEl) return
  await formEl.validate(async valid => {
    if (valid) {
      submitLoading.value = true
      try {
        const res = await editAccount(accountForm)
        if (res.code === 20000) {
          showAccountEditDialog.value = false
          ElMessage({
            showClose: true,
            message: '修改成功,正在跳转登录',
            type: 'success'
          })
          store.dispatch('base/logout').then(() => {
            router.push('/login')
          })
        }
      } catch (error) {
        console.error(error)
      } finally {
        submitLoading.value = false
      }
    }
  })
}

const handleEditAccount = () => {
  if (isPasswordVerified.value) {
    showAccountEditDialog.value = true
    accountForm.account = ''
    accountForm.code = ''
  } else {
    verifySource.value = 'account'
    verifyPasswordDialog.value = true
  }
}

const passwordFormRef = ref()
const showPasswordEditDialog = ref(false)
const passwordForm = reactive({
  account: '',
  oldPassword: '',
  newPassword: '',
  confirmNewPassword: ''
})

const validateNewPass = (rule, value, callback) => {
  const username = userInfo.name
  if (value === '') {
    callback(new Error('请输入密码'))
    return
  }
  
  if (value.length < 8) {
    callback(new Error('密码长度不能小于8位'))
    return
  }
  
  if (value.toLowerCase().includes(username.toLowerCase())) {
    callback(new Error('密码不能包含用名'))
    return
  }
  
  const hasUpperCase = /[A-Z]/.test(value)
  const hasLowerCase = /[a-z]/.test(value)
  const hasNumber = /[0-9]/.test(value)
  const hasSpecial = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(value)
  
  const matchCount = [hasUpperCase, hasLowerCase, hasNumber, hasSpecial].filter(Boolean).length
  if (matchCount < 3) {
    callback(new Error('密码必须包含大写字母、小写字母、数字、特殊字符中的至少三种'))
    return
  }
  
  callback()
}

const validateConfirmPass = (rule, value, callback) => {
  if (value === '') {
    callback(new Error('请再次输入密码'))
  } else if (value !== passwordForm.newPassword) {
    callback(new Error('两次输入密码不一致'))
  } else {
    callback()
  }
}

const passwordRules = reactive({
  newPassword: [{ validator: validateNewPass, trigger: 'blur', required: true }],
  confirmNewPassword: [{ validator: validateConfirmPass, trigger: 'blur', required: true }]
})

const handleEditPass = () => {
  if (isPasswordVerified.value) {
    showPasswordEditDialog.value = true
    passwordForm.account = userInfo.account
    passwordForm.oldPassword = verifyPasswordForm.password
    passwordForm.newPassword = ''
    passwordForm.confirmNewPassword = ''
  } else {
    verifySource.value = 'password'
    verifyPasswordDialog.value = true
  }
}

const submitPassword = async (formEl) => {
  if (!formEl) return
  await formEl.validate(async (valid) => {
    if (valid) {
      submitLoading.value = true
      try {
        const res = await resetPassword(passwordForm)
        if (res.code === 20000) {
          ElMessage({
            showClose: true,
            message: '密码修改成功，请重新登录',
            type: 'success'
          })
          showPasswordEditDialog.value = false
          store.dispatch('base/logout').then(() => {
            router.push('/login')
          })
        }
      } catch (error) {
        console.error(error)
      } finally {
        submitLoading.value = false
      }
    }
  })
}

const verifyPasswordDialog = ref(false)
const verifyPasswordForm = reactive({
  password: ''
})
const verifyPasswordFormRef = ref()
const verifyPasswordRules = reactive({
  password: [{ message: '请输入当前密码', trigger: 'blur', required: true }]
})

const verifyPassword = async (formEl) => {
  if (!formEl) return
  await formEl.validate(async (valid) => {
    if (valid) {
      submitLoading.value = true
      try {
        const res = await validPassword(verifyPasswordForm)
        if (res.code === 20000 && res.data) {
          isPasswordVerified.value = true
          verifyPasswordDialog.value = false
          if (verifySource.value === 'account') {
            showAccountEditDialog.value = true
          } else if (verifySource.value === 'password') {
            showPasswordEditDialog.value = true
            passwordForm.account = userInfo.account
            passwordForm.oldPassword = verifyPasswordForm.password
          }
        } else {
          ElMessage.error('密码错误')
        }
      } finally {
        submitLoading.value = false
      }
    }
  })
}

const countdown = ref(0)
const isSending = ref(false)

const sendVerifyCode = async () => {
  if (isSending.value) return
  if (!accountForm.account) {
    ElMessage.warning('请先输入手机号')
    return
  }

  if (accountForm.account === userInfo.account) {
    ElMessage.warning('新账号不能与当前账号相同')
    return
  }
  
  isSending.value = true
  const res = await getPhoneVarCode({ account: accountForm.account, terminal: '1' })
  if (res.code === 20000) {
    ElMessage.success('验证码发送成功')
    countdown.value = 60
    const timer = setInterval(() => {
      countdown.value--
      if (countdown.value <= 0) {
        clearInterval(timer)
        isSending.value = false
      }
    }, 1000)
  }
}

const verifySource = ref('')

onMounted(() => {
  getUserInfo().then(res => {
    Object.assign(userInfo, res.data)
    chooseAvatar.value = res.data.avatar
  })
})
</script>

<style scoped lang="scss">
.personal-message-setting {
  .message-title {
    height: 60px;
    font-size: 18px;
    display: flex;
    align-items: center;
    margin-bottom: 20px;
    span.tips {
      margin-left: 30px;
      font-weight: normal;
      @include tipsText;
    }
  }
  .personal-message-box {
    box-shadow: 0 0 4px rgba(#000, 0.04);
    background-color: #fff;
    padding: 0 20px 50px;
    .inner-personal-message {
      .info-item {
        display: flex;
        align-items: center;
        margin-bottom: 20px;
        min-height: 32px;
        .info-label {
          width: 120px;
        }
        .img-box {
          height: 120px;
          width: 120px;
          cursor: pointer;
          border-radius: 50%;
          overflow: hidden;
          position: relative;
          .no-avatar {
            display: flex;
            background-color: $mainColor;
            height: 100%;
            width: 100%;
            justify-content: center;
            align-items: center;
            p {
              color: #fff;
              font-size: 80px;
            }
          }
          .has-avatar {
            height: 100%;
            width: 100%;
            border-radius: 4px;
            img {
              height: 100%;
              width: 100%;
              border-radius: 4px;
            }
          }
          &:hover {
            .avatar-mask {
              opacity: 1;
            }
          }
          .avatar-mask {
            transition: all 0.3s;
            opacity: 0;
            position: absolute;
            width: 100%;
            height: 100%;
            background-color: rgba(#000, 0.4);
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 4px;
            p {
              text-align: center;
              font-size: 14px;
              color: #fff;
            }
          }
        }
      }
    }
  }
  .personal-message {
    margin-bottom: 20px;
  }
}

.avatar-list {
  display: flex;
  flex-wrap: wrap;
  height: 375px;
  padding: 10px;
  .online-upload-item {
    border: 1px solid #e4e4e4;
    height: 160px;
    width: calc(20% - 16px);
    background-color: $backBase;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 8px;
    cursor: pointer;
    box-sizing: border-box;
    transition: all 0.3s;
    position: relative;
    .upload-item-checkbox {
      position: absolute;
      height: 24px;
      width: 24px;
      box-sizing: border-box;
      border: 1px solid #dcdfe6;
      top: 5px;
      left: 5px;
      background-color: $white;
      display: none;
      transition: all 0.2s;
      align-items: center;
      justify-content: center;
      i {
        font-weight: bold;
        font-size: 18px;
        color: $white;
      }
    }
    img {
      max-width: 100%;
      max-height: 100%;
      object-fit: contain;
    }
    &.is-choose {
      .upload-item-checkbox {
        display: flex;
        background-color: #2cbf77;
        border-color: #2cbf77;
      }
    }
    &:hover {
      background-color: $focusContent;
      border-color: $hoverColor;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
      .upload-item-checkbox {
        display: flex;
      }
    }
  }
  overflow-y: auto;
  
  &::-webkit-scrollbar {
    width: 6px;
  }
  
  &::-webkit-scrollbar-thumb {
    background-color: #dcdfe6;
    border-radius: 3px;
  }
  
  &::-webkit-scrollbar-track {
    background-color: #f5f7fa;
  }
}
</style>
